import math
import numpy as np
import os
import xlsxwriter
import copy
import csv
import datetime
import dlib_recognition as fc
import math




PI = math.pi

def coup_sine(a,b,c,d,u,r,n,list_a,list_b,list_c,list_d):     # u为分段控制参数,r为耦合控制参数,n为序列长度
    tempa = r * a + (1 - r) * b
    tempb = r * b + (1 - r) * c
    tempc = r * c + (1 - r) * d
    tempd = r * d + (1 - r) * a
    for i in range(200):           #舍弃前200序列
        a = sine(tempa, u)
        b = sine(tempb, u)
        c = sine(tempc, u)
        d = sine(tempd, u)
        # list_a.append(a)
        # list_b.append(b)
        # list_c.append(c)
        # list_d.append(d)
        tempa = r * a + (1 - r) * b
        tempb = r * b + (1 - r) * c
        tempc = r * c + (1 - r) * d
        tempd = r * d + (1 - r) * a
    for i in range(n):
        a = sine(tempa, u)
        b = sine(tempb, u)
        c = sine(tempc, u)
        d = sine(tempd, u)
        list_a.append(a)
        list_b.append(b)
        list_c.append(c)
        list_d.append(d)
        tempa = r * a + (1 - r) * b
        tempb = r * b + (1 - r) * c
        tempc = r * c + (1 - r) * d
        tempd = r * d + (1 - r) * a


def sine(a, r1):        # a为初始值，r1为分段控制参数
    if a <= r1:
        a = math.sin(a * PI)
    elif a > r1 and a <= 1 / 2:
        a = math.sin((a - r1) * 2 * r1 / (1 - 2 * r1) * PI)
    elif a > 1 / 2 and a <= (1 - r1):
        a = math.sin((1 - r1 + (2 * a - 1) * r1 / (1 - 2 * r1)) * PI)
    else:
        a = math.sin(a * PI)
    a = a / math.sin(PI * r1)
    return a

def non_invertible_matrix(choatic_list1, choatic_list2,dimention):    #生成不可以矩阵
    array1 = np.array(np.identity(dimention))       #生成单位矩阵
    array2 = np.array(np.identity(dimention))
    int_list1 = []
    int_list2 = []
    for i in range(dimention):
        int_list1.append(int(choatic_list1[i] * 10000000) % dimention)
        int_list2.append(int(choatic_list2[i] * 10000000) % dimention)
    for j in range(dimention):
        temp1 = copy.deepcopy( array1[j] )
        array1[j] = array1[int_list1[j]]
        array1[int_list1[j]] = temp1
        temp2 = copy.deepcopy(array2[j])
        array2[j] = array2[int_list2[j]]
        array2[int_list2[j]] = temp2
    # print(array1)
    # print(array2)
    for i in range(dimention):
        for j in range(dimention):
            array2[i][j] = int(array1[i][j]) ^ int(array2[i][j])
    return array2



def vector_scramb(vector, choatic_list):
    for i in range(len(vector)):
        temp = int(choatic_list[i] * 100000) % len(vector)
        vector[i], vector[temp] = vector[temp], vector[i]
    return vector

def vector_rotation(vector, choatic_list1, choatic_list2, choatic_list3):
    def rotation(x,y,z, R_x, R_y, R_z):
        new_x = math.cos(R_y * PI) * math.cos(R_z * PI) * x + math.cos(R_y * PI) * math.sin(R_z * PI) * y - math.sin(R_y) * z
        new_y = (-math.cos(R_x) * math.sin(R_z) + math.sin(R_x) * math.sin(R_y) * math.cos(R_z)) * x + (math.cos(R_x) * math.cos(R_z) + math.sin(R_x) * math.sin(R_y) * math.sin(R_z)) * y  + math.sin(R_x) * math.cos(R_y) * z
        new_z = (math.sin(R_x) * math.sin(R_z) + math.cos(R_x) * math.sin(R_y) * math.cos(R_z)) * x + (-math.sin(R_x) * math.cos(R_z) + math.cos(R_x) * math.sin(R_y) * math.sin(R_z)) * y  + math.cos(R_x) * math.cos(R_y) * z
        list = []
        list.append(new_x)
        list.append(new_y)
        list.append(new_z)
        return (list)
    rotation_list = []
    vector_len = len(vector)
    if (len(vector) % 3)==0:    #向量维度是3的倍数
        for i in range(int(vector_len / 3)):
            temp = rotation(vector[i * 3], vector[i * 3 + 1], vector[i * 3 + 2], choatic_list1[i], choatic_list2[i], choatic_list3[i])
            rotation_list.append(temp[0])
            rotation_list.append(temp[1])
            rotation_list.append(temp[2])
    else:    #向量维度不是3的倍数
        for i in range(int(vector_len / 3)):  #先对3的倍数维度处理
            temp = rotation(vector[i * 3], vector[i * 3 + 1], vector[i * 3 + 2], choatic_list1[i], choatic_list2[i], choatic_list3[i])
            rotation_list.append(temp[0])
            rotation_list.append(temp[1])
            rotation_list.append(temp[2])
        #将最后三维组成一组，补齐
        temp = rotation(vector[vector_len -3], vector[vector_len -2], vector[vector_len-1], choatic_list1[vector_len -3], choatic_list2[vector_len -2], choatic_list3[vector_len -1])
        if (len(vector) % 3)==1:   #多余一维向量
            rotation_list.append(temp[2])
        elif (len(vector) % 3)==2:   #多余两维向量
            rotation_list.append(temp[1])
            rotation_list.append(temp[2])
    rotation_array = np.array(rotation_list)
    return rotation_array

def matirx_multiply(vector, matrix):
    list = []
    for i in range(len(vector)):
        temp = np.sum(np.multiply(vector, matrix[:,i] ))
        list.append(temp)
    return(np.array(list))





def comparePersonData(data1, data2):         #欧式距离，comparePersonData(vector1,vector2)?
    #两个向量的欧式距离越小，则两个向量的相似度越高
    diff = 0
    # for v1, v2 in data1, data2:
        # diff += (v1 - v2)**2
    for i in range(len(data1)):
        diff += (data1[i] - data2[i])**2
    diff = np.sqrt(diff)
    # print("Euclidean distance is: ", end="")
    # print(diff)
    # if(diff < 0.6):
    #     print( "It's the same person")
    # else:
    #     print ("It's not the same person")
    return diff



def listdir_2(path, list_name):           #获取文件夹中文件列表,不包含文件路径，只包含文件名称
    dirs  = os.listdir(path)
    for i in dirs:
        list_name.append(i)
    # for i in list_name:
    #     print(i)
    return list_name


def template_generate(vector, list_a, list_b, list_c, list_d, matrix):   #特征模板生成
    vector = vector_scramb(vector, list_a)
    vector = vector_rotation(vector, list_b, list_c, list_d)
    vector = vector_scramb(vector, list_b)
    vector = matirx_multiply(vector, matrix)
    return vector            #返回值作为图像生成的特征模板存储到数据库




if __name__ == '__main__':

    list_a=[]
    list_b=[]
    list_c=[]
    list_d=[]

    coup_sine(0.351, 0.620, 0.17, 0.29, 0.05, 0.995, 10000, list_a, list_b, list_c, list_d)   #  生成混沌序列
    #coup_sine的参数含义：前4个参数的取值范围为0到1的小数，第5个参数取值为0到0.1，第6个取值范围为0.9到1，第7个参数代表生成混沌序列的长度，最后4个参数用于存储生成的混沌序列

    matrix = non_invertible_matrix(list_c, list_d, 128)

    face_rec = fc.face_recognition()  # 创建对象
    face_rec.inputPerson(name='ccy0', img_path='D:/pohto/s1.jpg')  # name中写第一个人名字，img_name为图片名字，注意要放在faces文件夹中
    vector1 = face_rec.create128DVectorSpace()  # 提取128维向量，是dlib.vector类的对象

    # vector1中获得的数据即为提取到的人脸特征向量

   # print(vector1)

    vector = vector1   #将获取到的特征向量赋值给该变量

    template1 = template_generate(vector, list_a, list_b, list_c, list_d, matrix)
    #人脸图像注册阶段，将生成的template存储到数据库；在查询阶段，将生成的template和数据库中的所有记录进行比较
   #仅作测试

    face_rec = fc.face_recognition()  # 创建对象
    face_rec.inputPerson(name='ccy1', img_path='D:/pohto/s22.jpg')  # name中写第一个人名字，img_name为图片名字，注意要放在faces文件夹中
    vector2 = face_rec.create128DVectorSpace()  # 提取128维向量，是dlib.vector类的对象

    # vector1中获得的数据即为提取到的人脸特征向量

    # print(vector1)

    vector = vector2  # 将获取到的特征向量赋值给该变量

    template2 = template_generate(vector, list_a, list_b, list_c, list_d, matrix)

    print(template1)
    print(template2)
    bool1 = comparePersonData(template1,template2)
    print(bool1)


